<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

include_once 'ExceptionDAO.php';
include_once 'TOAutor.php';
include_once 'util/MapError.php';

/**
 * DAO para operações de banco para autor
 * 
 * @author Douglas Rafael
 */
class DAOAutor extends CI_Model {

    /**
     * Lista todos os autores cadastrados.
     * 
     * @param int    $init      Posição inicial do cursor
     * @param int    $quant     Total de registros
     * @param string $orderby   Nome da coluna a ser ordenada
     * @param string $direction Direção: ASC ou DESC
     * @return array TOAutor    Array de objetos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function select_all_authors($init, $quant, $orderby = NULL, $direction = NULL) {
        try {
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('id', 'ASC');
            $result = $this->db->get('autor', $quant, $init);

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar os autores.');
            } else {
                $autores = array();
                foreach ($result->result() as $value) {
                    $autor = new TOAutor();
                    $autor->id = $value->id;
                    $autor->nome = $value->nome;
                    array_push($autores, $autor);
                }
                return $autores;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Retorna o Total geral autores cadastrados.
     * 
     * @return int Total de resgistros
     */
    public function amount_all_authors() {
        return $this->db->count_all_results('autor');
    }
    
    /**
     * Seleciona um autor de acordo com seu id, ou nome (utilizando o like)
     * 
     * @param  TOAutor $email   Obejto contendo o id do autor a ser selecionado
     * @param  bool    $like    Se TRUE ao invés de selecionar pelo id do autor seleciona pelo nome, utilizando o like
     * @return TOAutor          Obejeto contendo o autor selecionado. É retornado apenas um autor
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_author(TOAutor $autor, $like = FALSE) {
        try {
            $like == FALSE ? $this->db->where("id", $autor->id) : $this->db->like("nome", $autor->nome);
            $result = $this->db->get('autor', 1);

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar selecionar autor.');
            } else {
                $value = $result->row();

                if (count($value) > 0) {
                    $autor = new TOAutor();
                    $autor->id = $value->id;
                    $autor->nome = $value->nome;
                } else {
                    $autor = NULL;
                }

                return $autor;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Insere no banco de dados o autor.
     * 
     * @param  TOAutor  $autor  Dados do autor a ser inserido
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_author(TOAutor $autor) {
        try {
            $result = $this->db->insert('autor', $autor);

            if (!$result) {
                throw new Exception();
            }
        } catch (Exception $erro) {
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            throw new ExceptionDAO($erro->getError($this->db->_error_number(), $this->db->_error_message(), $autor->nome));
        }
    }

    /**
     * Atualiza dados do autor
     * 
     * @param TOAutor $autor
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_author(TOAutor $autor) {
        try {
            $this->db->where('id', $autor->id);
            $result = $this->db->update('autor', $autor);

            if (!$result) {
                throw new Exception();
            }
        } catch (Exception $erro) {
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            throw new ExceptionDAO($erro->getError($this->db->_error_number(), $this->db->_error_message(), $autor->nome));
        }
    }

    /**
     * Excluir autor de acordo com o id.
     * 
     * @param TOAutor $autor
     * @throws ExceptionDAO 
     */
    public function delete_author(TOAutor $autor) {
        try {
            $this->db->where_in('id', $autor->id);
            $result = $this->db->delete('autor');

            if (!$result) {
                throw new Exception();
            }
        } catch (Exception $erro) {
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            throw new ExceptionDAO($erro->getError($this->db->_error_number(), $this->db->_error_message(), $autor->nome));
        }
    }

    /**
     * Efetua Busca por autor.
     * 
     * @param int $init
     * @param int $quant
     * @param string $term
     * @param string $orderby
     * @param string $direction
     * @return array TOAutor
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function search_author($init, $quant, $term = NULL, $orderby = NULL, $direction = NULL) {
        try {
            $this->db->like('id', $term);
            $this->db->or_like('nome', $term);
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('id', 'ASC');
            $result = $this->db->get('autor', $quant, $init);

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar buscar autor.');
            } else {
                $autores = array();
                foreach ($result->result() as $value) {
                    $autor = new TOAutor();
                    $autor->id = $value->id;
                    $autor->nome = $value->nome;
                    array_push($autores, $autor);
                }
                return $autores;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Retorna a quantidade de registros da busca
     * 
     * @param string $term
     * @return int
     */
    public function amount_search_author($term) {
        $this->db->like('id', $term);
        $this->db->or_like('nome', $term);

        return $this->db->count_all_results('autor');
    }

    /**
     * Retorna sugestões de autores de acordo com o term digitado
     * Útil para utilizar no autocomplete
     * 
     * @param TOAutor $autor
     * @return type
     */
    public function suggestion_author(TOAutor $autor) {
        $this->db->like('nome', $autor->nome);
        $result = $this->db->get('autor');

        $autores = array();
        if ($result) {
            foreach ($result->result() as $value) {
                $data['label'] = $value->nome;
                $data['id'] = $value->id;
                $data['nome'] = $value->nome;
                array_push($autores, $data);
            }
            return $autores;
        }
    }
    
    
    /**
     * Lista todos os autores cadastrados de um item (livro).
     * 
     * @param  int   $codigo_item   Código do item
     * @return array TOAutor        Array de objeto contendo dados do autor(es)
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_authors_item($codigo_item) {
        try {
            $this->db->select('autor.id, autor.nome');
            $this->db->join('autor', 'autor.id = autor_has_item.autor_id');
            $this->db->join('item', 'item.codigo = autor_has_item.item_codigo');
            $this->db->where('item.codigo', $codigo_item);
            $result = $this->db->get('autor_has_item');

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar autores do item.');
            } else {
                $autores = array();
                foreach ($result->result() as $value) {
                    $autor = new TOAutor();
                    $autor->id = $value->id;
                    $autor->nome = $value->nome;

                    array_push($autores, $autor);
                }
                return $autores;
            }
        } catch (ExceptionDAO $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Insere os autores do item (livro)
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_authors_item(TOItem $item) {
        try {
            $autores = array();
            foreach ($item->livro->autores as $value){
                $data['autor_id'] = $value->id;
                $data['item_codigo']  = $item->codigo;
                array_push($autores, $data);
            }
            $result = $this->db->insert_batch('autor_has_item', $autores);
            
            $this->db->trans_complete();

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar inserir autores do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Atualiza os autores do item (livro)
     * - 1° Os autores desse livro já cadastradas são apagadas, e depois inseridas as novas
     * 
     * @param  TOItem $item     Objeto contendo dados do item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_authors_item(TOItem $item) {
        try {
            $this->delete_authors_item($item->codigo);
            $autores = array();
            foreach ($item->livro->autores as $value) {
                $data['autor_id'] = $value->id;
                $data['item_codigo'] = $item->codigo;
                array_push($autores, $data);
            }
            $result = $this->db->insert_batch('autor_has_item', $autores);
            
            $this->db->trans_complete();

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar atualizar autores do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Remove os autores do item (livro)
     * 
     * @param  $codigo_item     Código do item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function delete_authors_item($codigo_item) {
        try {
            $this->db->where('item_codigo', $codigo_item);
            $result = $this->db->delete('autor_has_item');

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar remover autores do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

}